package com.jumi.microservice.utils;

import org.apache.commons.codec.digest.DigestUtils;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.w3c.dom.Document;
import org.w3c.dom.Element;
import org.w3c.dom.Node;
import org.w3c.dom.NodeList;
import org.xml.sax.InputSource;

import javax.xml.parsers.DocumentBuilder;
import javax.xml.parsers.DocumentBuilderFactory;
import java.io.StringReader;
import java.util.*;

/**
 * @author Dirk
 * @Date 2020-07-25 11:22
 */
public class WxBuildRequestUtil {

    private static final Logger log = LoggerFactory.getLogger(WxBuildRequestUtil.class);

    /**
     * 生成nonce_str
     *
     * @return
     */
    public static String getNonceStr() {
        Random random = new Random();
        return DigestUtils.md5Hex(String.valueOf(random.nextInt(10000)));
    }

    /**
     * 生成签名
     */
    public static String createSign(SortedMap<String, Object> sortedMap, String key) {

        StringBuilder sb = new StringBuilder();
        Set<Map.Entry<String, Object>> entrySet = sortedMap.entrySet();
        for (Map.Entry<String, Object> entry : entrySet) {
            String k = entry.getKey();
            Object v = entry.getValue();
            if (v != null && !"".equals(v) && !"key".equals(k) && !"sign".equals(k)) {
                sb.append(k).append("=").append(v).append("&");
            }
        }
        sb.append("key=").append(key);
        return DigestUtils.md5Hex(sb.toString()).toUpperCase();
    }

    /**
     * 校验签名
     *
     * @param parameters
     * @param key
     * @return
     */
    public static boolean checkSign(SortedMap<String, Object> parameters, String key) {
        String resSign = parameters.remove("sign").toString();
        if (resSign == null) {
            return false;
        }
        String sign = createSign(parameters, key);
        return resSign.equals(sign);
    }

    /**
     * 解析xml字符串转成map集合
     *
     * @param xml
     * @return
     */
    public static Map<String, String> doXMLParse(String xml) {
        Map<String, String> map = new HashMap<>();
        // 将编码改为UTF-8,并去掉换行符\空格等
        xml = xml.replaceFirst("encoding=\".*\"", "encoding=\"UTF-8\"");
        //去掉空白 换行符
        final StringBuilder sb = new StringBuilder(xml.length());
        char c;
        for (int i = 0; i < xml.length(); i++) {
            c = xml.charAt(i);
            if (c != '\n' && c != '\r' && c != ' ') {
                sb.append(c);
            }
        }
        xml = sb.toString();
        DocumentBuilderFactory factory = DocumentBuilderFactory.newInstance();
        try {
            DocumentBuilder documentBuilder = factory.newDocumentBuilder();
            StringReader reader = new StringReader(xml);
            InputSource inputSource = new InputSource(reader);
            Document document = documentBuilder.parse(inputSource);
            // 1.获取xml文件的根元素
            Element element = document.getDocumentElement();
            // 2.获取根元素下的所有子标签
            NodeList nodeList = element.getChildNodes();
            // 3.遍历子标签集合
            for (int i = 0; i < nodeList.getLength(); i++) {
                Node node = nodeList.item(i);
                map.put(node.getNodeName(), node.getFirstChild().getNodeValue());
            }
        } catch (Exception e) {
            log.error("xml解析异常：" + e);
        }

        return map;
    }

    /**
     * @param return_code 返回编码
     * @param return_msg  返回信息
     * @return
     * @Description：返回给微信的参数
     */
    public static String setXML(String return_code, String return_msg) {
        return "<xml><return_code><![CDATA[" + return_code
                + "]]></return_code><return_msg><![CDATA[" + return_msg
                + "]]></return_msg></xml>";
    }

    /**
     * @param parameters 请求参数
     * @return
     * @Description：将请求参数转换为xml格式的string
     */
    @SuppressWarnings("rawtypes")
    public static String getRequestXml(SortedMap<String, Object> parameters) {
        StringBuilder sb = new StringBuilder();
        sb.append("<xml>");
        Set<?> es = parameters.entrySet();
        for (Object o : es) {
            Map.Entry entry = (Map.Entry) o;
            String k = (String) entry.getKey();
            Object v = entry.getValue();
            if ("attach".equalsIgnoreCase(k) || "body".equalsIgnoreCase(k)
                    || "sign".equalsIgnoreCase(k)) {
                sb.append("<").append(k).append(">").append("<![CDATA[").append(v).append("]]></").append(k).append(">");
            } else {
                sb.append("<").append(k).append(">").append(v).append("</").append(k).append(">");
            }
        }
        sb.append("</xml>");
        try {
            return sb.toString();
        } catch (Exception e) {
            log.error("map转化成xml异常：" + e);
        }
        return "";
    }
}
